﻿namespace Launcher.View

import System
import System.Drawing
import System.Windows.Forms

import Launcher.Model
import Launcher.View.Organizer

callable ItemSelectedHandler(sender as object, item as RankingViewItem)
callable SelectedPageChangedHandler(item as RankingViewPage)
callable ClickHandler()

enum UIButtonType:
	Previous
	Next
	Close

class UIButton:
	_btype as UIButtonType
	
	event Clicked as ClickHandler
	
	[property(X)]
	_x as int
	
	[property(Y)]
	_y as int
	
	[property(Selected)]
	_selected as bool
	
	[property(Visible)]
	_visible = true
	
	def constructor(btype as UIButtonType):
		_btype = btype
		
	def Contains(x as int, y as int):
		dx = Math.Abs(x - _x - 32)
		dy = Math.Abs(y - _y - 32)
		
		return Math.Sqrt(dx*dx + dy*dy) <= 32
		
	def Paint(g as Graphics):
		return if not _visible
		
		g.FillEllipse(SolidBrush(Color.FromArgb(255, 64, 64, 64)),
						_x, _y, 64, 64)
		
		if _btype == UIButtonType.Previous:
			DrawPrevious(g)
		elif _btype == UIButtonType.Next:
			DrawNext(g)
		elif _btype == UIButtonType.Close:
			DrawClose(g)
			
	private def DrawPrevious(g as Graphics):
		d = 20
		y = _y + 8
		points = (Point(_x + d, y + 32),
					Point(_x + 64 - d, y + d), 
					Point(_x + 64 - d, y + 64 - d))
					
		g.FillPolygon(GetBrush(), points)
		
	private def GetBrush():
		if _selected:
			return SolidBrush(Color.FromArgb(255, 128, 128, 255))
		else:
			return SolidBrush(Color.FromArgb(255, 192, 192, 192))
		
	private def DrawNext(g as Graphics):
		d = 20
		y = _y + 8
		points = (Point(_x + 64 - d, y + 32),
					Point(_x + d, y + d), 
					Point(_x + d, y + 64 - d))
					
		g.FillPolygon(GetBrush(), points)
		
	private def DrawClose(g as Graphics):
		d = 14
		s = 5
		y = _y + 8
		mx = _x + 32
		my = y + 32
		points = (
					Point(mx + s, my),
					Point(mx + d, my + d),
					Point(mx, my + s),
					Point(mx - d, my + d),
					Point(mx - s, my),
					Point(mx - d, my - d),
					Point(mx, my - s),
					Point(mx + d, my - d))
					
		g.FillPolygon(GetBrush(), points)

	def Click():
		Clicked()

class RankingView:
"""Description of RankingView"""

	_model as StartMenuModel
	_pages as RankingViewModel
	_organizer as CircularOrganizer
	_parent as Form
	_toolTip as ToolTip
	_hoverItem as RankingViewItem

	_previousBtn = UIButton(UIButtonType.Previous)
	_nextBtn = UIButton(UIButtonType.Next)
	_closeBtn = UIButton(UIButtonType.Close)

	event ItemSelected as ItemSelectedHandler
	event SelectedPageChanged as SelectedPageChangedHandler
	event CloseClicked as ClickHandler
	
	def constructor(parent as Form, model as StartMenuModel):
		_parent = parent
		_model = model
		_toolTip = ToolTip(ShowAlways: true)
		BindModel()
		
		_previousBtn.Clicked += { PreviousPage() }
		_nextBtn.Clicked += { NextPage() }
		_closeBtn.Clicked += { OnCloseClicked() }
		
		SelectedPageChanged += _OnPageChanged
		
	private def OnCloseClicked():
		CloseClicked()
		
	private def _OnPageChanged(page):
		_previousBtn.Visible = not IsFirstPage()
		_nextBtn.Visible = not IsLastPage()
		
	private def BindModel():
		_pages = RankingViewModel(_model)
		_pages.ItemChanged += _OnItemChanged
		_pages.ItemSizeChanged += _OnItemSizeChanged
		_organizer = CircularOrganizer(_pages.SelectedPage.Items)

	private def _OnItemChanged(item as RankingViewItem):
		_pages.Repaginate()
		_parent.Invalidate()

	private def _OnItemSizeChanged(item as RankingViewItem):
		_organizer.Items = _pages.SelectedPage.Items
		_parent.Invalidate()

	def Paint(g as Graphics, width as int, height as int):
		_organizer.Items = _pages.SelectedPage.Items
		_organizer.Update(width, height)
		_organizer.DrawBackground(g)
		MoveButtons(width, height)

		for b in (_previousBtn, _nextBtn, _closeBtn):
			b.Paint(g)

		for v as RankingViewItem in _organizer.Items:
			v.DrawItem(g)
						
	def MouseMove(e as MouseEventArgs):
		for v as RankingViewItem in _organizer.Items:
			v.MouseMove(e.X, e.Y)
			DetectEnterLeave(v, e.X, e.Y)

		for b in (_previousBtn, _nextBtn, _closeBtn):
			b.Selected = b.Contains(e.X, e.Y)
			
		_parent.Invalidate()
			
	private def DetectEnterLeave(v as RankingViewItem, x as int, y as int):
		if v.Contains(x, y):
			if v is not _hoverItem:
				_hoverItem = v
				OnEnter(v, x, y)
		else:
			if v is _hoverItem:
				OnLeave(v)
			
	private def OnEnter(v as RankingViewItem, x as int, y as int):
		_toolTip.Show(FormatToolTipText(v.TooltipText), _parent, x, y + 32)
		
	private def OnLeave(v as RankingViewItem):
			_toolTip.Hide(_parent)
			_parent.Invalidate()

	private def FormatToolTipText(text as string):
		sb = System.Text.StringBuilder()
		line = ""
		words = text.Split(char(' '))
		for w in words:
			line += w
			if len(line) > 25:
				sb.Append(line)
				sb.Append("\n")
				line = ""
			else:
				line += " "
				
		return sb.ToString().Trim()

	def MouseClick(e as MouseEventArgs):
		for v as RankingViewItem in _organizer.Items:
			if v.Contains(e.X, e.Y):
				ItemSelected(self, v)

		for b in (_previousBtn, _nextBtn, _closeBtn):
			if b.Contains(e.X, e.Y):
				b.Click()

	def Update(visible as bool):
		if visible:
			_pages.Repaginate()
			SelectedPageChanged(_pages.SelectedPage)
			_parent.Invalidate()
		else:
			ResetItemsDrawSize()
			
	private def ResetItemsDrawSize():
		for i as RankingViewItem in _pages.SelectedPage.Items:
			i.ResetDrawSize()
			
	def NextPage():
		if _pages.Next():
			SelectedPageChanged(_pages.SelectedPage)
			_parent.Invalidate()
		
	def PreviousPage():
		if _pages.Previous(): 
			SelectedPageChanged(_pages.SelectedPage)
			_parent.Invalidate()
			
	def IsFirstPage():
		return _pages.IsFirst()
		
	def IsLastPage():
		return _pages.IsLast()
		
	private def MoveButtons(w as int, h as int):
		d = _organizer.Distance 
		midx = w / 2
		midy = h / 2
		
		_previousBtn.X = midx - 32 - 64 - 16
		_previousBtn.Y = midy + d - 32 - 16

		_closeBtn.X = midx - 32
		_closeBtn.Y = midy + d - 32

		_nextBtn.X = midx + 32 + 16
		_nextBtn.Y = midy + d - 32 - 16
